import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { CreateSpecDto, CreateSpecValueDto } from './dto/create-spec.dto';
import { UpdateSpecDto, UpdateSpecValueDto } from './dto/update-spec.dto';
import { InjectEntityManager, InjectRepository } from '@nestjs/typeorm';
import { Spec } from './entities/spec.entity';
import { EntityManager, Repository } from 'typeorm';
import { FindSpecDto } from './dto/find-spec.dto';
import { SpecValue } from './entities/specValue.entity';
import { FindValueSpecDto } from './dto/findValue-spec.dto';
import { DeleteIds } from '../dto/all-dto';
import { Good } from '../good/entities/good.entity';
import { Sku } from '../sku/entities/sku.entity';

@Injectable()
export class SpecService {
  constructor(
    @InjectRepository(Spec)
    private specRepository: Repository<Spec>,
    @InjectEntityManager()
    private entityManager: EntityManager,
    @InjectRepository(Good)
    private goodRepository: Repository<Good>,
  ) {
  }

  async create(createSpecDto: CreateSpecDto) {
    const { name, remake, goodId } = createSpecDto;
    const { raw } = await this.specRepository.createQueryBuilder('spec').insert().values({
      name,
      ...(remake && { remake }),
      good: await this.goodRepository.createQueryBuilder().where('id = :id', { id: goodId }).getOne(),
    }).execute();
    if (!raw.insertId) {
      throw new HttpException('创建失败', HttpStatus.INTERNAL_SERVER_ERROR);
    }

    return raw.insertId;
  }

  async findAll(findSpecDto: FindSpecDto) {
    const { name, page, pageSize } = findSpecDto;
    const specBuilder = this.specRepository.createQueryBuilder();
    if (name) {
      specBuilder.andWhere('name LIKE :name', { name: `%${name}%` });
    }
    const [list, total] = await specBuilder.skip((page - 1) * pageSize).take(pageSize).getManyAndCount();
    return {
      list,
      total,
    };
  }

  async findList() {
    return '1';
  }

  async findOne(findSpecDto: FindSpecDto) {
    return `This action updates a spec`;
  }

  update(id: number, updateSpecDto: UpdateSpecDto) {
    return `This action updates a #${id} spec`;
  }

  async remove(deleteIds: DeleteIds) {
    // const {affected} = await  this.specRepository.createQueryBuilder()
    //  .delete()
    //  .whereInIds(deleteIds.ids)
    //  .execute()
    // if(affected===0){
    //   throw new HttpException('删除失败', HttpStatus.INTERNAL_SERVER_ERROR);
    // }
    // await this.entityManager.transaction(async transactionalEntityManager => {
    //   await Promise.all(deleteIds.ids.map(async (num) => {
    //     let list = await transactionalEntityManager
    //       .createQueryBuilder(SpecValue, 'specValue')
    //       .leftJoinAndSelect('specValue.spec', 'spec')
    //       .where('spec.id = :id', { id: num })
    //       .select('specValue.id')
    //       .getMany();
    //
    //     list = list.map((item: any) => item.id);
    //
    //     await transactionalEntityManager.createQueryBuilder(SpecValue, 'specValue')
    //       .leftJoinAndSelect('specValue.spec', 'spec')
    //       .delete()
    //       .where('spec.id = :id', { id: num })
    //       .whereInIds(list)
    //       .execute();
    //
    //     await transactionalEntityManager.createQueryBuilder(Spec, 'spec')
    //       .delete()
    //       .where('id = :id', { id: num })
    //       .execute();
    //   }));
    //   return true;
    // });
    // return '操作成功';
    await this.entityManager.transaction(async transactionalEntityManager => {
      await Promise.all(deleteIds.ids.map(async (num) => {
        let list = await transactionalEntityManager.createQueryBuilder(SpecValue, 'specValue')
          .where('specValue.spec = :id', { id: num })
          .getMany();
        await  Promise.all(list.map(async item => {
          await transactionalEntityManager.createQueryBuilder(Sku, 'sku')
            .delete()
            .where(`JSON_CONTAINS_PATH(sku.specCombination, 'one', '$."${item.id}"')`) // 检查是否存在 key
            .execute();
        }))

      }));

      // await transactionalEntityManager.createQueryBuilder(SpecValue, 'specValue')
      //   .delete()
      //   .whereInIds(deleteIds.ids)
      //   .execute();
      await transactionalEntityManager.createQueryBuilder(Spec,'spec').delete().where('spec.id = :id', { id: deleteIds.ids }).execute();
    });
    // await this.specRepository.createQueryBuilder().delete().where('id = :id', { id: deleteIds.ids }).execute();
    return '操作成功';
  }
}

@Injectable()
export class SpecValueService {
  constructor(
    @InjectRepository(Spec)
    private specRepository: Repository<Spec>,
    @InjectRepository(SpecValue)
    private specValueRepository: Repository<SpecValue>,
    @InjectEntityManager()
    private entityManager: EntityManager,
  ) {
  }

  async findAll(findValueSpecDto: FindValueSpecDto) {
    const { value, page, pageSize, id } = findValueSpecDto;
    const [list, total] = await this.specValueRepository.createQueryBuilder('specValue')
      .leftJoinAndSelect('specValue.spec', 'spec')
      .andWhere('spec.id = :id', { id })
      .skip((page - 1) * pageSize)
      .take(pageSize)
      .getManyAndCount();

    return {
      list,
      total,
    };
  }

  async create(createSpecValueDto: CreateSpecValueDto) {
    const { value, id } = createSpecValueDto;
    const res = await this.findOne(value, id);
    console.log(res);
    if (res) {
      throw new HttpException('规格值名字重复', HttpStatus.INTERNAL_SERVER_ERROR);
    }
    const { raw } = await this.specValueRepository.createQueryBuilder().insert().values({
      value,
      spec: await this.specRepository.createQueryBuilder().where('id = :id', { id }).getOne(),
    }).execute();
    return raw.insertId;
  }

  async remove(deleteIds: DeleteIds) {
    await this.entityManager.transaction(async transactionalEntityManager => {
      await Promise.all(deleteIds.ids.map(async (num) => {
        await transactionalEntityManager.createQueryBuilder(Sku, 'sku')
          .delete()
          .where(`JSON_CONTAINS_PATH(sku.specCombination, 'one', '$."${num}"')`) // 检查是否存在 key
          .execute();
      }));

      await transactionalEntityManager.createQueryBuilder(SpecValue, 'specValue')
        .delete()
        .whereInIds(deleteIds.ids)
        .execute();
    });
  }

  async update(updateSpecValueDto: UpdateSpecValueDto) {
    const { id, value, parentId } = updateSpecValueDto;
    const res = await this.findOne(value, parentId);
    console.log(res);
    if (res) {
      throw new HttpException('规格值不可重复', HttpStatus.INTERNAL_SERVER_ERROR);
    }
    const { affected } = await this.specValueRepository.createQueryBuilder()
      .update()
      .set({ value })
      .where('id = :id', { id })
      .execute();

    if (affected === 0) {
      throw new HttpException('修改失败', HttpStatus.INTERNAL_SERVER_ERROR);
    }
    return '操作成功';
  }

  async findOne(value: string, id: string | number) {
    return await this.specValueRepository.createQueryBuilder('specValue')
      .leftJoinAndSelect('specValue.spec', 'spec')
      .where('spec.id = :id', { id })
      .andWhere('specValue.value = :value', { value })
      .getOne();
  }
}